Developing a Search Component for KM Search iView |
Table of Contents
Applies To:
Knowledge Management 6.0
Summary
Customizable search interfaces are absolutely necessary for providing company-specific search functionality for KM content. Since the introduction of functionality for creating search dialogs with search components, it is possible to develop customized search components and plug them into the standard search iView of KM.
Relevant Knowledge Management APIs
A prerequisite for developers starting search component implementation is an understanding of the concepts described in Repository Framework Concepts (RCO).
This tutorial describes the usage of the following Knowledge Management APIs that are relevant for implementing your own search component:
com.sapportals.wcm.control.util.search.*: Contains interfaces and classes for implementing search components.
com.sapportals.wcm.service.indexmanagement.*: Contains interfaces and classes to for building query elements for searches.
com.sapportals.htmlb.*: Contains HTMLB classes for creating UI elements of the search component.
Coding in Detail
The standard KM search iView offers the capability of plugging in custom-developed search components that define certain areas of the iView. There is the following default iView layout:
Developing new search components means implementing the ISearchComponent interface. It is necessary to implement certain methods that are called by the standard search iView and that must return certain values. This sample search component shows a list of buzzwords which are added to the search term, if they are selected.
The sequence diagram of a single call stack is shown in the diagram below:
Implementing an ISearchComponent
The ISearchComponent interface offers some important method signatures to be implemented in order to get a valid search component.
To render the control in the standard search iView, an HTMLB compliant control has to be returned by the renderComponent() method:
public Component renderComponent() throws SearchException {
For example, take any HTMLB layout object for defining a certain area within the standard search iView:
GridLayout grid = new GridLayout();
grid.setWidth("100%");grid.setCellPadding(5);
grid.addComponent(2,1, this.createHeader());
grid.addComponent(3,1, this.createBody());
grid.addComponent(4,1, new HTMLFragment("<hr size=\"1\">"));return grid;
}
The method should throw a SearchException when an error occurs during rendering.
The rendered HTMLB component can contain all HTMLB controls that can be used for input handling from the user, such as InputField, Checkbox, Radiobuttons:
GridLayout grid = new GridLayout();
grid.setWidth("100%");int col = 1, row = 1;
for (int i=0;i<SimpleSearchComponent.m_buzzwords.length;i++) { if (i%7==0) {col = 1;
row++;
}
Checkbox c =
new Checkbox(SimpleSearchComponent.m_buzzwords[i]);
c.setText(value);
c.setChecked(false);
grid.addComponent(row , col, c);
col ++;
}
return grid;
After the UI is rendered by the standard KM search iView and the user executes the search by pressing the search button, the UI elements of the rendered search component are evaluated by the standard KM search iView by calling the setDynpage() method. It provides access to every HTMLB element that is placed on the layout control:
public void setDynPage(DynPage dynPage) {StringBuffer searchWord = new StringBuffer();
Component c = null;
Retrieve all UI elements from the current Dynpage. Do not persist the dynpage object itself. It is created anew for every server roundtrip.
for (int i=0;i<SimpleSearchComponent.m_buzzwords.length;i++) {c = dynPage.getComponentByName(
SimpleSearchComponent.m_buzzwords[i]
);
if (c!=null && c instanceof Checkbox) { if (((Checkbox)c).isChecked()) {searchWord.append(c.getId());
searchWord.append(SimpleSearchComponent.SEPARATOR);
}
}
}
The values of every UI element can be stored in the local persistent map, which is validated for every server roundtrip for the corresponding search component:
this.getPersistenceMap().setProperty(
SimpleSearchComponent.PRP_SEARCH_WORDS,
searchWord.toString());
}
The result of an executed search can be modified by adding a valid query (IQueryEntryList) created by the information specified in the UI elements. The query itself must be put in a SearchParamsMap object that contains search-relevant key value pairs:
public SearchParamsMap getSearchParamsMap() {SearchParamsMap m = new SearchParamsMap();
try {IQueryEntryList list = this.createQuery();
The IQueryEntryList must be put into the SearchParamsMap object with a certain key:
m.put(SearchParamConst.PARAM_SEARCH_QUERY_ENTRIES, list);
} catch (WcmException e) {e.printStackTrace();
}
return m;
}
SearchParamConst.PARAM_SEARCH_QUERY_ENTRIES key is evaluated by the standard KM search iView. You can put in the following subset of keys defined in the SearchParamConst class:
|
Parameter |
Purpose |
Type |
Possible values |
|
PARAM_SEARCH_IN |
Search scope selection |
String |
SEARCH_INDEXES SEARCH_FROM_FOLDER (-> Search Folder) |
|
PARAM_SEARCH_FOLDER |
Search folder (-> PARAM_SEARCH_IN) |
String |
Example: /documents |
|
PARAM_SEARCH_QUERY_ENTRIES |
Search query list |
IQueryEntryList |
Complex object that can be built by SearchQueryBuilder |
|
PARAM_INDICES_LIST |
Index list to be searched on |
ArrayList |
Array list of index objects |
|
PARAM_SORT_PROP_NAME |
Property for sorting the search results |
ISortPropertyName |
CM property object with sort order (has major priority) |
|
PARAM_SORT_ORDER |
Sort order of search result |
String |
DESCENDING,ASCENDING |
|
PARAM_SORT_OPTION |
Property ID for sorting search results |
String |
|
|
PARAM_MATCHES_PER_PAGE |
Number of search results per page |
String |
Numeric values: 5,10,20,50 |
|
PARAM_ALLOWED_SORT_PROPS |
Property IDs of allowed sort properties to be shown in the search result header (csv) |
String |
Example: displayname,modified,modifiedby |
|
PARAM_MAX_NOF_CATEGORIES |
Maximum number of categories to be displayed for one search result |
String |
Numeric values: 0,1,2,3,4,6,9999 |
|
PARAM_MAX_SNIPPET_WORDS |
Defines content snippet length for search result abstracts |
String |
Numeric values 0-200 |
|
PARAM_ENABLE_SEARCH_CASCADE |
Enables cascaded search (see documentation) |
Boolean |
true,false |
|
PARAM_SEARCH_TERM |
Search term for display in search result header; is not taken into account for query |
String |
Example: Banana |
|
PARAM_ERRORS_OCCURREDOCCURED (read-only) |
Return value that indicates that at least one error occurred in at least one component; Is set to true when provided messageList of components is not empty; useful when input checks have to be performed; |
Boolean |
true, false |
|
PARAM_JUST_SEARCHED (read-only) |
Return value that indicates that a search was performed |
Boolean |
true |
Keep in mind that all keys stored in the merged map of the standard KM search iView are overwritten by the last placed value, except the key SearchParamConst.PARAM_SEARCH_QUERY_ENTRIES. This key’s values are connected by a logical AND.
In case no parameter is specified, the parameter’s values are taken from the defined Search option set. If no special option set is choosen the default values are taken. It is recommended to customize UI settings within the KM config iView -> Content Management -> UserInterface -> Search.
A helper method for creating valid IQueryEntryLists could look like this:
private IQueryEntryList createQuery() throws WcmException {StringBuffer query = new StringBuffer();
StringTokenizer words = new StringTokenizer(
this.getPersistenceMap().getProperty(
SimpleSearchComponent.PRP_SEARCH_WORDS, ""
), SimpleSearchComponent.SEPARATOR);
Create a simple search term by concatenating a string object out of UI elements stored in the persistence map.
while (words.hasMoreTokens()){query.append(words.nextToken());
if (words.hasMoreTokens())
query.append(SimpleSearchComponent.OPERATOR);
}
Create a valid IQueryEntryList object retrieved from the standard SearchQueryBuilder instance.
SearchQueryBuilder sqb = new SearchQueryBuilder();
sqb.setSearchTerm(query.toString());
return sqb.buildSearchQueryEntries();
}
Alternatively, you can build your own IQueryEntryList objects retrieving an empty instance from the IFederatedSearch:
IIndexService indexService =
(IIndexService) ResourceFactory
.getInstance()
.getServiceFactory()
.getService(
IServiceTypesConst.INDEX_SERVICE);
IFederatedSearch federatedSearch =
(IFederatedSearch) indexService.getObjectInstance(
IWcmIndexConst.FEDERATED_SEARCH_INSTANCE);
IQueryEntryList qel = federatedSearch.getNewQueryEntryList();
IPropertyName propName = new PropertyName(
PropertyName.createDisplayname().getNamespace(),
earchParamConst.PROP_NAME_COLLECTION);
Create a query and set the important attributes and add a new entry to the entry list.
IQueryEntry queryEntry = federatedSearch.getNewQueryEntry();
queryEntry.setPropertyName(propName);
queryEntry.setRowType(IQueryEntry.ROW_TYPE_ATTRIBUTE);
queryEntry.setValue("true");queryEntry.setPropertyOperator(
IQueryEntry.PROPERTY_OPERATOR_EQUAL
);
queryEntry.setTermWeight(1.0F);
qel.add(queryEntry);
Methods to be implemented by an ISearchComponent implementation:
|
Method |
Purpose |
|
renderComponent() |
Renders the custom search component based on an HTMLB layout, for example, a grid layout. |
|
setDynPage() |
Sets the current dynpage object from the standard KM search iView to evaluate user’s input. |
|
getSearchParamsMap() |
Returns a map with search relevant information. All parameters filled into the map are overwritten by the last placed call, except for SearchParamConst.PARAM_SEARCH_QUERY_ENTRIES. This key’s values are merged by an logical AND |
Configuration
After deployment of the search component within a valid PAR file structure, the technical mapping has to be carried out in the user interface configuration of the KM configuration iView.
The mapping from a Java class to a component alias can be carried out at Content Management -> User Interface -> Mapping -> Search Dialog Box Component. Create a new entry for the custom search component.
A unique alias and a valid java class must be provided. The java class specified here must implement the ISearchComponent interface and contain the methods mentioned above.
The search component is now registered in the KM infrastructure. It can be configured as a component of a certain component set. A search component set is used in a search iView instance:
The standard iView is now ready to use the search component. After you execute a search request, the following screen should appear:
Known limitations
Please keep in mind the following NetWeaver Notes. They describe some limitations in the current release:
OSS Note 743130: Section III. NW04 SP Stack 04: Content Management and Collaboration.
Sample SearchComponent
The following archive contains a valid and deployable SAP NetWeaver Developer Studio project based on KM API of NW04 SPS 4, which shows the steps described above in a whole example.